package com.gitee.qdbp.base.settings.redis;

import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.springframework.beans.factory.FactoryBean;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis集群客户端<br>
 * <pre>
&lt;bean class="com.xxx.JedisClusterFactory" init-method="init"&gt;
    &lt;!-- redis.servers=192.168.1.101:6379,192.168.1.102:6379,... --&gt;
    &lt;property name="servers" value="${redis.servers}" /&gt;
    &lt;property name="password" value="${redis.password:}" /&gt;
    &lt;property name="timeout" value="300000" /&gt;
    &lt;property name="maxAttempts" value="6" /&gt;
    &lt;property name="jedisPoolConfig"&gt;
        &lt;bean class="redis.clients.jedis.JedisPoolConfig"&gt;
            &lt;property name="maxTotal" value="200" /&gt;
            &lt;property name="maxIdle" value="50" /&gt;
            &lt;property name="maxWaitMillis" value="60000" /&gt;
            &lt;property name="testOnBorrow" value="true" /&gt;
        &lt;/bean&gt;
    &lt;/property&gt;
&lt;/bean&gt;
 * </pre>
 * 
 * @author zhaohuihua
 * @version 160421
 */
public class JedisClusterFactory implements FactoryBean<JedisCluster> {

    private static final Pattern IP_PORT = Pattern.compile("^.+:\\d{1,5}$");

    /** 服务器IP端口, 多个地址以逗号分隔 **/
    private String servers;

    private JedisCluster jedisCluster;

    // 以下是JedisCluster的各种参数
    private Integer timeout;
    private Integer connectionTimeout; // = connectionTimeout || timeout
    private Integer soTimeout; // = soTimeout || timeout
    @Deprecated // = maxAttempts
    private Integer maxRedirections;
    private Integer maxAttempts;
    private String password;
    private JedisPoolConfig jedisPoolConfig;

    @Override
    public JedisCluster getObject() throws Exception {
        return jedisCluster;
    }

    @Override
    public Class<? extends JedisCluster> getObjectType() {
        return (this.jedisCluster != null ? this.jedisCluster.getClass() : JedisCluster.class);
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    // 初始化
    public void init() {
        // 解析IP地址
        String[] strings = servers.split(",");
        Set<HostAndPort> haps = new HashSet<>();
        for (String string : strings) {
            if (!IP_PORT.matcher(string).matches()) {
                throw new IllegalArgumentException("redis servers format error!");
            }
            String[] ipAndPort = string.split(":");

            haps.add(new HostAndPort(ipAndPort[0].trim(), Integer.parseInt(ipAndPort[1].trim())));
        }

        // 构造JedisCluster对象
        Integer connectionTimeout = this.connectionTimeout != null ? this.connectionTimeout : this.timeout;
        Integer soTimeout = this.soTimeout != null ? this.soTimeout : this.timeout;
        Integer maxAttempts = this.maxAttempts != null ? this.maxAttempts : this.maxRedirections;
        String password = this.password == null || this.password.length() == 0 ? null : this.password;
        jedisCluster = new JedisCluster(haps, connectionTimeout, soTimeout, maxAttempts, password, jedisPoolConfig);
    }

    /** 服务器IP端口, 多个地址以逗号分隔 **/
    public String getServers() {
        return servers;
    }

    /** 服务器IP端口, 多个地址以逗号分隔 **/
    public void setServers(String servers) {
        this.servers = servers;
    }

    public Integer getTimeout() {
        return timeout;
    }

    public void setTimeout(Integer timeout) {
        this.timeout = timeout;
    }

    public Integer getConnectionTimeout() {
        return connectionTimeout;
    }

    public void setConnectionTimeout(Integer connectionTimeout) {
        this.connectionTimeout = connectionTimeout;
    }

    public Integer getSoTimeout() {
        return soTimeout;
    }

    public void setSoTimeout(Integer soTimeout) {
        this.soTimeout = soTimeout;
    }

    /** @deprecated use maxAttempts **/
    @Deprecated
    public Integer getMaxRedirections() {
        return maxRedirections;
    }

    /** @deprecated use maxAttempts **/
    @Deprecated
    public void setMaxRedirections(Integer maxRedirections) {
        this.maxRedirections = maxRedirections;
    }

    public Integer getMaxAttempts() {
        return maxAttempts;
    }

    public void setMaxAttempts(Integer maxAttempts) {
        this.maxAttempts = maxAttempts;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public JedisPoolConfig getJedisPoolConfig() {
        return jedisPoolConfig;
    }

    public void setJedisPoolConfig(JedisPoolConfig jedisPoolConfig) {
        this.jedisPoolConfig = jedisPoolConfig;
    }

}
